package junits.compile_junit;

import com.hedl.practice.diyJava.junit.compile_junit.test.Factorial;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import static org.junit.Assert.assertEquals;        //自己导包
import static org.junit.Assert.assertTrue;

/**
 * 测试类上加上@RunWith和@ContextConfiguration注解，告诉JUnit测试类需要使用Spring容器来运行测试：
 * 注意的是，@ContextConfiguration注解中的classpath路径需要与applicationContext.xml文件的路径一致。
 * 最后，需要确保applicationContext.xml文件中有关于Factorial类的Bean配置信息
 */
@RunWith(SpringJUnit4ClassRunner.class)
//@RunWith(JUnit4.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class Main {
    @Autowired
    Factorial factorial;


    //测试乘阶
    @Test
    public void testFactorial(){
        if (factorial.fact(10) == 3628800){
            System.out.println("pass");
        }else {
            System.out.println("fail");
        }
    }

    /**
     * 测试junit断言方法；
     * assertEquals(期望值,计算乘阶值)
     *
     * 在测试方法内部，我们用assertEquals(1, Factorial.fact(1))表示，期望Factorial.fact(1)返回1。
     * assertEquals(expected, actual)是最常用的测试方法，它在Assertion类中定义。Assertion还定义了其他断言方法，例如：
     *      assertTrue(): 期待结果为true
     *      assertFalse(): 期待结果为false
     *      assertNotNull(): 期待结果为非null
     *      assertArrayEquals(): 期待结果为数组并与期望数组每个元素的值均相等
     *
     * 单元测试可以确保单个方法按照正确预期运行，如果修改了某个方法的代码，只需确保其对应的单元测试通过，即可认为改动正确。
     * 此外，测试代码本身就可以作为示例代码，用来演示如何调用该方法。
     * 使用JUnit进行单元测试，我们可以使用断言（Assertion）来测试期望结果，可以方便地组织和运行测试，并方便地查看测试结果。
     * 此外，JUnit既可以直接在IDE中运行，也可以方便地集成到Maven这些自动化工具中运行。
     *
     * 在编写单元测试的时候，我们要遵循一定的规范：
     *      一是单元测试代码本身必须非常简单，能一下看明白，决不能再为测试代码编写测试；
     *      二是每个单元测试应当互相独立，不依赖运行的顺序；
     *      三是测试时不但要覆盖常用测试用例，还要特别注意测试边界条件，例如输入为0，null，空字符串""等情况。
     * 小结:
     *      JUnit是一个单元测试框架，专门用于运行我们编写的单元测试：
     *      一个JUnit测试包含若干@Test方法，并使用Assertions进行断言，注意浮点数assertEquals()要指定delta。
     */
    @Test
    public void testFact(){
        assertEquals(1,factorial.fact(1));
        assertEquals(2,factorial.fact(2));
        assertEquals(6,factorial.fact(3));
        //assertEquals(362880,factorial.fact(10));        //这里将不会通过断言，因为这里期望值不符合我们的乘阶计算出来的值
        assertEquals(2432902008176640000L,factorial.fact(20));
        /**
         * 使用浮点数时，由于浮点数无法精确地进行比较，
         * 因此，我们需要调用assertEquals(double expected, double actual, double delta)这个重载方法，指定一个误差值：
         */
        assertEquals(0.1,Math.abs(1-9/10.0),0.0000001);
    }
}
